package org.fixies.database.dbunit;

import org.dbunit.dataset.*;
import org.dbunit.dataset.datatype.DataType;
import org.fixies.spreadsheet.Cell;
import org.fixies.spreadsheet.Unit;
import org.fixies.spreadsheet.Row;
import org.fixies.utils.Validator;

import java.util.ArrayList;
import java.util.List;


/**
 * org.dbunit.dataset.ITableの実装クラス
 *
 * @author Kawasaki
 * @see org.dbunit.dataset.ITable
 */
public class TableImpl extends AbstractTable {

    private final ITableMetaData tableMetaData_;

    private final String[][] data_;

    /**
     * コンストラクタ
     *
     * @param unit
     */
    public TableImpl(Unit unit) {
        Validator.notNull(unit);
        String type = unit.getMetaData("TYPE");
        if (!"TABLE".equals(type)) {
            throw new IllegalArgumentException("#TYPE must be TABLE."
                    + "but was [" + type + "] ");
        }

        String tableName = unit.getMetaData("TABLE");
        if (Validator.isNullOrEmpty(tableName)) {
            throw new IllegalArgumentException("invalid table name ["
                    + tableName
                    + "]");
        }
        // 先頭行はカラム名を表す。
        Row columnRow = unit.iterator().next();

        tableMetaData_ = createMetaData(tableName, columnRow);
        data_ = unit.toStringArray();
    }


    /**
     * DBUnit用メタデータを作成する。
     *
     * @param tableName テーブル名
     * @param sampleRow カラム名を格納した行
     * @return テーブルメタデータ
     */
    private ITableMetaData createMetaData(String tableName, Row sampleRow) {
        List<Column> columnList = new ArrayList<Column>(sampleRow.size());
        for (Cell cell : sampleRow) {
            columnList.add(new Column(cell.asString(), DataType.UNKNOWN));
        }
        Column[] columns = columnList.toArray(new Column[columnList.size()]);
        return new DefaultTableMetaData(tableName, columns);
    }

    /**
     * @see org.dbunit.dataset.ITable#getTableMetaData()
     */
    public ITableMetaData getTableMetaData() {
        return tableMetaData_;
    }

    /**
     * @see org.dbunit.dataset.ITable#getRowCount()
     */
    public int getRowCount() {
        return data_.length - 1;
    }

    /**
     * @see org.dbunit.dataset.ITable#getValue(int, java.lang.String)
     */
    public Object getValue(int rowIndex, String column) throws DataSetException {
        assertValidRowIndex(rowIndex);

        int columnIndex = getColumnIndex(column);
        String[] row = null;
        try {
            row = data_[rowIndex + 1];
        } catch (IndexOutOfBoundsException e) {
            throw new RowOutOfBoundsException(e);
        }
        String value = row[columnIndex];
        if (value == null || value.equals("NULL")) {
            return null;
        }
        return value;
    }
}
